// @ts-check
const manifest = require('./manifest')()
const { Route, out } = require('f2e-serve')
const postcss = require('postcss')
const namespacePluginForPostcss = require('./plugins/namespacePluginForPostcss')

const prefixClass = `.${manifest.name}`

/** @type {import('memory-tree').MemoryTree.MemoryTree} */
let _memory
exports.onContextReady = (ctx) => _memory = ctx.memory

/** @type {import('f2e-server').MiddlewareCreater} */
const builder = function (conf) {
    let need_update = false
    const route = new Route()
    route.on('listen', out.ServerSent(() => {
        let result = need_update
        need_update = false
        return result + ''
    }, { interval: 500 }))

    // 添加选择器前缀
    const styleWrapper = async (pathname = '', css = '') => {
        const result = await postcss.default([
            namespacePluginForPostcss({ namespace: prefixClass })
        ]).process(css, { from: conf.root })
        return result.css + '\n//# sourceMappingURL=' + pathname.split('/').pop() + '.map\n'
    }
    // 封闭全局变量
    const scriptWrapper = (() => {
        const DEV_SERVER = `http://localhost:${conf.port}`
        let prefix = '(function (){ var __SCOPE__, RunScope, __CONFIG__ = {}; '
        const suffix = '; })();'
        if (conf.livereload) {
            prefix += `__CONFIG__=${JSON.stringify({
                DEV_SERVER, LOG_LEVEL: 'DEBUG',
            })}; `
        }
        return (content = '') => `${prefix}${content}${suffix}`
    })()
    return {
        setBefore: -1,
        onSet: async (pathname, d, store) => {
            if (pathname === 'config/manifest.js') {
                return {
                    data: JSON.stringify(manifest, null, 4),
                    outputPath: 'manifest.json',
                }
            }
        },
        onGet: async (pathname, d, store) => {
            if (/assets\/.*?\.css$/.test(pathname)) {
                return styleWrapper(pathname, d?.toString())
            }
            if (/^js\/\w+\.js$/.test(pathname)) {
                return scriptWrapper(d?.toString())
            }
        },
        onRoute: route.execute,
        buildWatcher: !conf.livereload ? undefined : ((init) => (p, e, build, store) => {
            if (!init) {
                init = true
                store.onBuildingChange(async function (isBuilding) {
                    if (!isBuilding && _memory) {
                        await _memory.output('')
                        // 输出完成
                        need_update = true
                    }
                })
            }
        })(false)
    }
}
exports.builder = builder